﻿using Protocolo.Mensajes.Request;
using System.Threading;
using Protocolo.Enums;
using System;
using Protocolo.Utilidades;

namespace Servidor
{
    public class ProcesosSincronizacionServidores
    {
        // Permite acceso seguro de varios subprocesos
        private volatile bool _shouldStop;

        public void AtenderSincronizacionServidores()
        {
            while (!_shouldStop)
            {
                try
                {
                    // Recibir mensaje de servidores y sincrinizar contenido
                    var request = new EnviarDatosServidorRequest();
                    request.RecibirBroadcast(DatosServidor.Instancia.PuertoUDPSincronizarServidores);

                    //Valido que no sea yo mismo quien manda el mensaje
                    if (request.IPServidor != DatosServidor.Instancia.IPServidor)
                    {
                        //Utilities.LogMessage(string.Format("Mensaje sincronizacion recibido de servidor {0}", request.IPServidor));

                        var datosServidor = new SyncAnchoDeBanda()
                        {
                            AnchoDeBanda = request.AnchoDeBanda,
                            FechaRecibido = DateTime.Now,
                            IntervaloSincronizacion = request.IntervaloSincronizacion
                        };

                        if (!DatosServidor.Instancia.Servidores_AnchoDeBanda.ContainsKey(request.IPServidor))
                        {
                            // Es un servidor nuevo, guardamos sus datos
                            DatosServidor.Instancia.Servidores_AnchoDeBanda.Add(request.IPServidor, datosServidor);
                        }
                        else
                        {
                            // El servidor ya existe debemos actualizar sus datos
                            DatosServidor.Instancia.Servidores_AnchoDeBanda[request.IPServidor] = datosServidor;
                        }

                        foreach (string archivo in request.dicArchivosMD5.Keys)
                        {
                            if (!DatosServidor.Instancia.Archivos_MD5.ContainsKey(archivo))
                            {
                                try
                                {
                                    Utilities.LogMessage(string.Format("Descargando archivo {0} desde {1}", archivo, request.IPServidor));

                                    var requestArchivo = new DescargarArchivoRequest();
                                    requestArchivo.NombreArchivo = archivo;
                                    requestArchivo.ByteDesde = 0;
                                    var response = requestArchivo.DescargarArchivo(request.IPServidor, request.TCPServidor, DatosServidor.Instancia.FileRepository, null);

                                    if (response.Resultado == ResultadoTransferenciaArchivoEnum.OK)
                                    {
                                        DatosServidor.Instancia.Archivos_MD5.Add(archivo, response.MD5);
                                        Utilities.LogExito(string.Format("Archivo {0} descargado con exito desde servidor {1}", archivo, request.IPServidor));
                                    }
                                    else
                                    {
                                        Archivos.EliminarArchivo(string.Format("{0}\\{1}", DatosServidor.Instancia.FileRepository, archivo));
                                        Utilities.LogError(string.Format("Error descargando archivo {0} desde servidor {1}: {2}", archivo, request.IPServidor, ObtenerMensajeEnum.ResultadoTransferenciaArchivo(response.Resultado)));
                                    }
                                }
                                catch(Exception ex)
                                {
                                    Archivos.EliminarArchivo(string.Format("{0}\\{1}", DatosServidor.Instancia.FileRepository, archivo));
                                    Utilities.LogError(string.Format("Error descargando archivo {0} desde servidor {1}: {2}", archivo, request.IPServidor, ex.Message));
                                }
                            }
                        }
                    }
                }
                catch(Exception ex)
                {
                    Utilities.LogError(string.Format("Error sincronizando servidores {0}", ex.Message));
                }
            }
        }
        
        public void EnviarDatosServidor()
        {
            while (!_shouldStop)
            {
                try
                {
                    // Envio los datos del servidor por broadcast
                    var request = new EnviarDatosServidorRequest();
                    request.IPServidor = DatosServidor.Instancia.IPServidor;
                    request.TCPServidor = DatosServidor.Instancia.PuertoTCPSincronizarServidores;
                    request.AnchoDeBanda = DatosServidor.Instancia.AnchoDeBandaServidor.AnchoDeBandaDisponible;
                    request.IntervaloSincronizacion = DatosServidor.Instancia.IntervaloSincronizacionServidores;
                    request.dicArchivosMD5 = DatosServidor.Instancia.Archivos_MD5;

                    request.EnviarBroadcast(DatosServidor.Instancia.PuertoUDPSincronizarServidores);

                    //Espero para volver a enviar los datos
                    Thread.Sleep(DatosServidor.Instancia.IntervaloSincronizacionServidores * 1000);
                }
                catch (Exception ex)
                {
                    Utilities.LogError(string.Format("Error enviando datos de servidor {0}", ex.Message));
                }
            }
        }

        public void RequestStop()
        {
            _shouldStop = true;
        }
       

    }
}
